package handlers

import (
	"backend/pkg/log"
	"backend/pkg/utils"
	"net/http"
	"time"

	"math/rand"

	"github.com/gin-gonic/gin"
	"github.com/mojocn/base64Captcha"
	"github.com/spf13/viper"
)

const (
	DefaultVerificationCodeExpiry = 10 * time.Minute
	MinVerificationCodeExpiry     = 1 * time.Minute
)

var store = base64Captcha.DefaultMemStore

var emailVerificationCodes = make(map[string]struct {
	code      string
	expiresAt time.Time
})

func init() {
	// 设置配置文件
	viper.SetConfigName("config")       // 配置文件名称(无扩展名)
	viper.SetConfigType("yaml")         // 如果配置文件名称中没有扩展名，则需要配置此项
	viper.AddConfigPath(".")            // 查找配置文件所在的路径
	viper.AddConfigPath("./config")     // 多个配置路径
	viper.AddConfigPath("$HOME/.myapp") // 可以添加多个搜索路径

	// 读取环境变量
	viper.AutomaticEnv()

	// 尝试读取配置文件
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			log.Info("未找到配置文件，将使用环境变量")
		} else {
			log.Error("读取配置文件错误: %v", err)
		}
	}
}

func GenerateCaptcha(c *gin.Context) {
	startTime := time.Now()

	driver := base64Captcha.NewDriverDigit(80, 240, 6, 0.7, 80)
	captcha := base64Captcha.NewCaptcha(driver, store)
	id, b64s, _, err := captcha.Generate()

	if err != nil {
		log.Error("验证码生成失败: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "验证码生成失败"})
		log.RequestLog(c, startTime, "验证码生成失败")
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"captchaId":  id,
		"captchaImg": b64s,
	})

	log.RequestLog(c, startTime, "验证码生成成功")
}

func VerifyCaptcha(id string, value string) bool {
	return store.Verify(id, value, true)
}

func GenerateEmailCode(c *gin.Context) {
	startTime := time.Now()
	log.Info("收到邮箱验证码请求")

	var req struct {
		Email string `json:"email" binding:"required,email"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		log.Error("邮箱验证请求参数错误: %v, 原始请求体: %v", err, c.Request.Body)
		c.JSON(http.StatusBadRequest, gin.H{"error": "邮箱格式不正确"})
		log.RequestLog(c, startTime, "邮箱验证请求参数错误")
		return
	}

	log.Info("准备为邮箱 %s 生成验证码", req.Email)

	// 生成6位随机验证码
	code, expiresAt := generateVerificationCode()
	emailVerificationCodes[req.Email] = struct {
		code      string
		expiresAt time.Time
	}{code, expiresAt}
	log.Debug("生成的验证码: %s, 过期时间: %s", code, expiresAt.Format(time.RFC3339))

	// 获取邮箱配置
	smtpFrom := viper.GetString("SMTP_FROM")
	smtpHost := viper.GetString("SMTP_HOST")
	smtpPort := viper.GetString("SMTP_PORT")
	log.Debug("邮箱配置 - SMTP_FROM: %s, SMTP_HOST: %s, SMTP_PORT: %s",
		smtpFrom, smtpHost, smtpPort)

	// 发送验证码邮件
	err := utils.SendEmail(req.Email, "验证码", "您的验证码是: "+code)
	if err != nil {
		log.Error("验证码邮件发送失败: %v, 目标邮箱: %s", err, req.Email)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "验证码发送失败"})
		log.RequestLog(c, startTime, "验证码邮件发送失败")
		return
	}

	log.Info("验证码发送成功 - 邮箱: %s, 耗时: %v", req.Email, time.Since(startTime))

	c.JSON(http.StatusOK, gin.H{
		"message": "验证码已发送到您的邮箱",
	})

	// 记录验证码存储状态
	log.Debug("当前存储的验证码数量: %d", len(emailVerificationCodes))
	log.RequestLog(c, startTime, "验证码发送成功")
}

func VerifyEmailCode(email string, code string) bool {
	stored, exists := emailVerificationCodes[email]
	if !exists {
		return false
	}

	// 检查是否过期
	if time.Now().After(stored.expiresAt) {
		delete(emailVerificationCodes, email)
		return false
	}

	// 验证成功后删除验证码
	if stored.code == code {
		delete(emailVerificationCodes, email)
		return true
	}
	return false
}

func generateVerificationCode() (string, time.Time) {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	code := ""
	for i := 0; i < 6; i++ {
		code += string(rune(r.Intn(10) + '0'))
	}
	// 设置10分钟过期时间
	expiresAt := time.Now().Add(getVerificationCodeExpiry())
	return code, expiresAt
}

// 添加获取过期时间的函数
func getVerificationCodeExpiry() time.Duration {
	// 从配置中获取过期时间（单位：分钟）
	expiryMinutes := viper.GetInt("VERIFICATION_CODE_EXPIRY_MINUTES")
	if expiryMinutes <= 0 {
		return DefaultVerificationCodeExpiry
	}

	expiry := time.Duration(expiryMinutes) * time.Minute
	if expiry < MinVerificationCodeExpiry {
		return MinVerificationCodeExpiry
	}

	return expiry
}
